/****************************************************************************************
 ** Server is an application to manage several clients inside a thread.
 ** Copyright (C) 2013  Francesc Martinez <es.linkedin.com/in/cescmm/en>
 **
 ** This library is free software; you can redistribute it and/or
 ** modify it under the terms of the GNU Lesser General Public
 ** License as published by the Free Software Foundation; either
 ** version 2.1 of the License, or (at your option) any later version.
 **
 ** This library is distributed in the hope that it will be useful,
 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 ** Lesser General Public License for more details.
 **
 ** You should have received a copy of the GNU Lesser General Public
 ** License along with this library; if not, write to the Free Software
 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 ***************************************************************************************/

#include <QtCore>
#include "Server.h"
#include "ClientSocket.h"
#include "ProcessMessage.h"

Server::Server(QObject *parent) : QTcpServer(parent)
{
}

Server::~Server()
{
}

void Server::incomingConnection(int socketDescriptor)
{
	ClientThread *client = new ClientThread(socketDescriptor);
	connect(client, SIGNAL(receivedMessage(QByteArray)), this, SLOT(processMsg(QByteArray)));
	connect(client, SIGNAL(clientClosed(int)), this, SLOT(threadFinished(int)), Qt::DirectConnection);
	connect(client, SIGNAL(finished()), client, SLOT(deleteLater()));

	clientList.append(client);
	clientManager.addUser(client);

	client->start();
}

void Server::processMsg(const QByteArray &msg)
{
	ClientThread *clSender = (ClientThread*)sender();

	ProcessMessage input(msg, clSender, &clientManager);
	QByteArray output = input.process();
	if(output.size() == 0) return;

	clSender->sendMessage(output);
}


void Server::threadFinished(int threadId)
{
	QString userExited;

	for (int i = 0; i < clientList.size(); i++)
	{
		if (clientList.at(i)->getThreadId() == threadId)
		{
			clientManager.updateStatus(clientList.at(i), USER_OFFLINE);
			clientManager.removeUser(clientList.at(i));

			userExited = clientList.at(i)->getClient()->getName();
			clientList.removeAt(i);
		}
	}

	//Message to the other clients
	/*Protocol *newUser = new Protocol();
	newUser->setHeader(Protocol::CLIENT_EXIT);
	newUser->setBody("User has left!");
	newUser->setOtherCommands("user", userExited);
	
	for (int i = 0; i < clientList.size(); i++)
		clientList.at(i)->sendMessage(newUser->getFullMessage().toLatin1());
	*/
	//delete newUser;

	//QLog_Trace("Server", "Thread finished");
}

QList<ClientSocket*> Server::getClients() const
{
	QList<ClientSocket*> clients;

	for (int i = 0; i < clientList.size(); i++)
		clients.append(clientList.at(i)->getClient());

	return clients;
}

ClientSocket * Server::getClient(int _id) const
{
	for (int i = 0; i < clientList.size(); i++)
		if (clientList.at(i) and clientList.at(i)->getClient()->getId() == _id)
			return clientList.at(i)->getClient();

	return NULL;
}

ClientSocket * Server::getClientByName(const QString &_name) const
{
	for (int i = 0; i < clientList.size(); i++)
		if (clientList.at(i) and clientList.at(i)->getClient()->getName() == _name)
				return clientList.at(i)->getClient();

	return NULL;
}

void Server::writeToClients(const QString &_msg)
{
	for (int i = 0; i < clientList.size(); i++)
		clientList.at(i)->sendMessage(_msg.toLatin1());
}
